/*

有些成员变量的数据类型比较特别，它们的初始化方式也和普通数据类型的成员变量有所不同。这些特殊的类型的成员变量包括：

a.引用

b.常量

c.静态

d.静态常量(整型)

e.静态常量(非整型)

    常量和引用，必须通过参数列表进行初始化。
    静态成员变量的初始化也颇有点特别，是在类外初始化且不能再带有static关键字，其本质见文末。

1.静态成员属于类作用域，但不属于类对象，和普通的static变量一样，程序一运行就分配内存并初始化，生命周期和程序一致。
静态成员在每个类中只有一个拷贝，是解决同一个类的不同对象之间数据和函数共享问题的。
所以，在类的构造函数里初始化static变量显然是不合理的。
静态成员其实和全局变量地位是一样的，只不过编译器把它的使用限制在类作用域内（不是类对象，它不属于类对象成员），要在类的定义外（不是类作用域外）初始化。

2.所以使用前置声明静态成员就可以保证编译通过。

3.
出现在类体外的函数定义不能指定关键字static；
静态成员之间可以相互访问，包括静态成员函数访问静态数据成员和访问静态成员函数；
非静态成员函数可以任意地访问静态成员函数和静态数据成员；
静态成员函数不能访问非静态成员函数和非静态数据成员；
由于没有this指针的额外开销，因此静态成员函数与类的全局函数相比速度上会有少许的增长；
调用静态成员函数，可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数，
当同一类的所有对象使用一个量时，对于这个共用的量，可以用静态数据成员变量，这个变量对于同一类的所有的对象都取相同的值。
静态成员变量只能被静态成员函数调用。静态成员函数也是由同一类中的所有对象共用。只能调用静态成员变量和静态成员函数。

*/
//参考下面的代码以及其中注释：

#include <iostream>
using namespace std;

class BClass
{
public:
 BClass() : i(1), ci(2), ri(i){} // 对于常量型成员变量和引用型成员变量，必须通过参数化列表的方式进行初始化
                                //普通成员变量也可以放在函数体里，但是本质其实已不是初始化，而是一种普通的运算操作-->赋值运算，效率也低
 static void print();
 void print_no_static();
private:
 int i;                                  // 普通成员变量
 const int ci;                           // 常量成员变量
 int &ri;                                // 引用成员变量
 static int si;                          // 静态成员变量
 //static int si2 = 100;                 // error: 只有静态常量成员变量，才可以这样初始化
 static const int csi;                   // 静态常量成员变量
 static const int csi2 = 100;            // 静态常量成员变量的初始化(Integral type)    (1)
 static const double csd;                // 静态常量成员变量(non-Integral type)
 //static const double csd2 = 99.9;      // error: 只有静态常量整型数据成员才可以在类中初始化

};

//注意下面三行：不能再带有static
int BClass::si = 0; // 静态成员变量的初始化(Integral type)
const int BClass::csi = 1; // 静态常量成员变量的初始化(Integral type)
const double BClass::csd = 99.9; // 静态常量成员变量的初始化(non-Integral type)

// 在初始化(1)中的csi2时，根据著名大师Stanley B.Lippman的说法下面这行是必须的。
// 但在VC2003中如果有下面一行将会产生错误，而在VC2005中，下面这行则可有可无，这个和编译器有关。
const int BClass::csi2;

void BClass::print()
{
	std::cout << "static param func:" << std::endl; 
	//std::cout << "ci:" << i << std::endl; //静态成员函数不能访问非静态成员函数和非静态数据成员；
	//std::cout << "ci:" << ci << std::endl; //静态成员函数不能访问非静态成员函数和非静态数据成员；
	std::cout << "si:" << si << std::endl; 
}

void BClass::print_no_static()
{
	print();//非静态成员函数可以任意地访问静态成员函数和静态数据成员；
}

int main()
{
     BClass b;
     b.print();
     BClass::print();
     return 0;
}
